/*
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with this program; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *    2010 year
 *    Author: Michael Khromov aka MikeDM (Mike D'Morto)
 *    E-Mail: mikedmorto@gmail.com
 */

#include <QtGui>
#include <QPluginLoader>
#include <QSplashScreen>
#include <QPixmap>
#include <QDebug>
#include <QTranslator>
#include "def.h"
#include "tslog.h"
#include "iface_dbplugin.h"
#include "iface_wrkplugin.h"
#include "iface_loginplug.h"
#include "iface_seplugin.h"
#include "tsiniter.h"
#include "mainwin.h"

int main(int argc, char ** argv){
    QApplication app(argc, argv);
    // инициализируем протоколирование событий с уровнем 1 по умолчанию.
    // fixit добавить возможность смены уровня протоколирования через параметры и через конфигурационный файл.
    TsLog log;
    log.slotPut("core",3,"Debug: Start");

    // парсинг аргументов.
    // аргументы переданные приложению имеют больший приоритет чем конфиг.
    // список доступных аргументов
    // -h --help собственно помощь
    // -v --version версия
    // -d --debug уровень протоколирования
    // -c --config путь до конфигурационного файл
    // -p --plugins-dir путь до каталога плагинов
    // -db --database инициализационная строка базы данных в виде "pl_db_mysql,server_addr,user,pass,dbname"
    //      где имя плагина бд, адрес, пользователь, пароль, имя базы.
    // -fd --filebase путь до хранилища файлов.
    // -l --login инициализационная строка системы авторизации в виде "pl_login_std,noauto,USER"
    //      где имя плагина, и параметры этого плагина, в нашем случае логин плагин настроен так:
    //      noauto отключен автологин, дефолтное имя USER
    QString paramsConfigPath="";
    QString paramsdb="";
    QString paramsPlPath="";
    QString paramsLogin="";
    QString paramsFb="";
    for(int i = 0 ; i < app.arguments().size(); i ++){
        //qDebug()<<"arg "<<i<<app.arguments().at(i);
        if(app.arguments().at(i) == "-p" or
           app.arguments().at(i) == "--plugins-dir"){
            if(app.arguments().size() > i+1 ){
                if( QString(app.arguments().at(i+1)).toInt() >= 0){
                    // берем строку конфигурации баз данных
                    paramsPlPath=app.arguments().at(i+1);
                }
            }

        }

        if(app.arguments().at(i) == "-fb" or
           app.arguments().at(i) == "--filebase"){
            if(app.arguments().size() > i+1 ){
                if( QString(app.arguments().at(i+1)).toInt() >= 0){
                    // берем строку конфигурации файлового хранилища
                    paramsFb=app.arguments().at(i+1);
                }
            }

        }
        if(app.arguments().at(i) == "-db" or
           app.arguments().at(i) == "--database"){
            if(app.arguments().size() > i+1 ){
                if( QString(app.arguments().at(i+1)).toInt() >= 0){
                    // берем строку конфигурации баз данных
                    paramsdb=app.arguments().at(i+1);
                }
            }

        }
        if(app.arguments().at(i) == "-l" or
           app.arguments().at(i) == "--login"){
            if(app.arguments().size() > i+1 ){
                if( QString(app.arguments().at(i+1)).toInt() >= 0){
                    // берем строку конфигурации плагина логина
                    paramsLogin=app.arguments().at(i+1);
                }
            }

        }

        if(app.arguments().at(i) == "-h" or
           app.arguments().at(i) == "--help"){
            //fixit add help text
            exit(0);
        }

        if(app.arguments().at(i) == "-v" or
           app.arguments().at(i) == "--version"){
            printf("%s version %s.%s build %s\n",QString(APP_NAME).toStdString().c_str(),
                   QString(app_major_v).toStdString().c_str(),
                   QString(app_minor_v).toStdString().c_str(),
                   QString(app_build_v).toStdString().c_str());
            exit(0);
        }

        if(app.arguments().at(i) == "-d" or
           app.arguments().at(i) == "--debug"){
            if(app.arguments().size() > i+1 ){
                if( QString(app.arguments().at(i+1)).toInt() >= 0){
                    // устанавливаем новый уровень протоколирования в лог.
                    log.setLevel(QString(app.arguments().at(i+1)).toInt());
                }
            }
        }

        if(app.arguments().at(i) == "-c" or
           app.arguments().at(i) == "--config"){
            if(app.arguments().size() > i+1 ){
                paramsConfigPath=QString(app.arguments().at(i+1));

            }

        }
    }

    // читаем конфиг, если путь до конфига был передан параметром то читаем его.
    // очередность проверки наличия конфига:
    // 1 - путь до конфига был передан параметром при запуске.
    //
    // 3 - конфиг в дефолтном каталоге пользователя (в юникс системах это ~/.torisakura/

    // проверяем есть ли файл конфига по пути из параметров
    bool next=true;
    QSettings * cfg;
    if(paramsConfigPath!=""){
        // путь есть, тестируем его
        if(QFile::exists(paramsConfigPath)){
            // все гуд, файл есть, подключаем его.
            cfg = new QSettings(paramsConfigPath,QSettings::IniFormat);
            // читаем тестовую строку, версия конфига
            if(cfg->value("main/cfgver","").toString() == cfgver){
                // все гуд, наш конфиг
                // лочим проверку других конфигов ибо наш конфиг загружен.
                next=false;
            }else{
                // поскольку конфиг косячный, удаляем.
                delete cfg;
            }
        }
    }

    if(next){
        /*
        QString fPath;
        #ifdef Q_OS_WIN32
        fPath=app.applicationDirPath()+"/tscore.cfg";
        #endif
        #ifdef Q_OS_LINUX
        fPath=app.applicationDirPath()+"/../etc/tscore.cfg";
        //fixit сделать для маков и для прочих.
        #endif
        */
        // предидущая проверка не увенчалась успехом
        // читаем дефолтный конфиг
        //if(QFile::exists(fPath)){
            // все гуд, файл есть, подключаем его.
            cfg = new QSettings("ToriSakura","tscore");
            // читаем тестовую строку, версия конфига
            if(cfg->value("main/cfgver","").toString() == cfgver){
                // все гуд, наш конфиг
                // лочим проверку других конфигов ибо наш конфиг загружен.
                next=false;
            }else{
                // поскольку конфиг косячный, удаляем.
                delete cfg;
            }
        //}
    }

    if(next){
        // конфиг файл не был подключен. жалуемся в лог беда беда.
        log.slotPut("core",1,"Error: config file not found or corrupted.");
    }

    // проверяем наличие пути до файловой базы
    if(paramsFb==""){
        // путь до файловой базы небыл передан при инициализации, роем конфиг
        if(cfg->value("main/filebase","").toString()==""){
            // ну все приплыли, нету у нас файловой базы. ругаемся и завершаемся.
            log.slotPut("core",-1,"Critical Error: failure get path to filebase.");
            QMessageBox::critical(NULL,APP_NAME,"Critical Error: failure get path to filebase.");
            exit(1);
        }else{
            paramsFb=cfg->value("main/filebase").toString();
        }
    }


// берем строку плагина базы данных и подключаем плагин там указанный.
    QStringList qdb; // распарсенные опции подключения базы данных
    if(paramsdb!=""){
        // в параметрах приложения была указана строка базы данных
        qdb=paramsdb.split(",");

    }else{
        // строка указана небыла, пробуем выдернуть с конфига
        // предварительно проверям есть ли конфиг вообще.
        if(next){
            // конфиг то тютю. ругаемся матом.
            log.slotPut("core",1,"Error: read configuration fail");
            QMessageBox::critical(NULL,APP_NAME,"Error: read configuration fail");
            exit(1);
        }else{
            // конфиг есть.
        qdb=cfg->value("main/db","").toString().split(",");

        }
    }
    // проверяем размер qdb, если оно не равно хотябы 1 то косякс, ругаемся и выходим.

    if(qdb.size()==0){
        // тушите свечи сударь.
        log.slotPut("core",1,"Error: database plugin not set");
        QMessageBox::critical(NULL,APP_NAME,"Error: error database plugin not set");
        exit(1);
    }

    // все в поряде, выводим 1 позицию, это и есть плагин баз данных, остальные строки это его конфигурация.

    // ищем путь до плагинов, порядок таков:
    // 1 - путь переданный в параметрах при старте
    // 2 - путь из конфига
    // 3 - статично прописанный в коде приложения.
    bool db_plug_enabled=false; // индикатор состояния плагина баз данных, загружен или нет.
    TsIfaceDbPlugin * PlugDB; // указатель на плагин баз данных
    if(QFile::exists(paramsPlPath+plugin_prefix+qdb.at(0)+plugin_suffix)){
        // файлег есть, подключаем плагин.
        QPluginLoader ldr;
        ldr.setFileName(paramsPlPath+plugin_prefix+qdb.at(0)+plugin_suffix);
        if(ldr.load()){
            // плагин загружен, инициализируем.
            db_plug_enabled=true;
            PlugDB = qobject_cast<TsIfaceDbPlugin*>(ldr.instance());
            log.slotPut("core",2,"Success: load database plugin <"+qdb.at(0)+
                        "> from path <"+paramsPlPath+plugin_prefix+qdb.at(0)+plugin_suffix+">");
        }else{
            // плагин по этому пути не был загружен, ничего страшного, может по след путям загрузится
            log.slotPut("core",2,"Error: database plugin <"+qdb.at(0)+
                        "> not loaded from path <"+paramsPlPath+plugin_prefix+qdb.at(0)+plugin_suffix+">");
        }
    }else{
        // файлега нету, ищем дальше
        log.slotPut("core",2,"Information: database plugin <"+qdb.at(0)+
                    "> file not found <"+paramsPlPath+plugin_prefix+qdb.at(0)+plugin_suffix+">");
        // следующий файлег должен лежать по пути из конфига
        // для начала проверяем есть ли конфиг вообще =)
        if(!next){
            log.slotPut("core",2,"Information: config found");
            // конфиг есть, лопатим конфиг и проверяем наличие файлега по этому пути

            if(QFile::exists(cfg->value("main/plugins","").toString()
                +plugin_prefix+qdb.at(0)+plugin_suffix)){

                // файлен есть, загружаем плугин
                QPluginLoader ldr;
                ldr.setFileName(cfg->value("main/plugins","").toString()
                                +plugin_prefix+qdb.at(0)+plugin_suffix);
                if(ldr.load()){
                    log.slotPut("core",2,"Success: load database plugin <"+qdb.at(0)+
                                "> from path <"+cfg->value("main/plugins","").toString()
                                +plugin_prefix+qdb.at(0)+plugin_suffix+">");
                    // плагин загружен, инициализируем.
                    db_plug_enabled=true;
                    PlugDB = qobject_cast<TsIfaceDbPlugin*>(ldr.instance());
                }else{
                    // плагин по этому пути не был загружен, ничего страшного, может по след путям загрузится
                    log.slotPut("core",2,"Error: database plugin <"+qdb.at(0)+
                                "> not loaded from path <"+cfg->value("main/plugins","").toString()
                                +plugin_prefix+qdb.at(0)+plugin_suffix+">");
                }
            }else{
                // и тут файлега нету, да и черт с ним.

            }
        }
        //конфига нету, да и черт с ним, идем по пути прописаному статично
        if(!db_plug_enabled){

            // из конфига не поймали, значит ищем по дефолтному пути
            if(QFile::exists(QString(plugin_dir)+QString(plugin_prefix)+qdb.at(0)+QString(plugin_suffix))){
                // файлен есть, загружаем плугин
                QPluginLoader ldr;
                ldr.setFileName(QString(plugin_dir)+QString(plugin_prefix)+qdb.at(0)+QString(plugin_suffix));
                if(ldr.load()){
                    // плагин загружен, инициализируем.
                    db_plug_enabled=true;
                    PlugDB = qobject_cast<TsIfaceDbPlugin*>(ldr.instance());
                    log.slotPut("core",2,"Success: load database plugin <"+qdb.at(0)+
                                "> from path <"+QString(plugin_dir)+
                                QString(plugin_prefix)+qdb.at(0)+QString(plugin_suffix)+">");
                }else{
                    // плагин и по этому пути не был загружен, вот это уже беда, и критическая, ругаемси и тушим свечи.
                    log.slotPut("core",-1,"Critical Error: database plugin <"+qdb.at(0)+
                                "> not loaded from path<"+plugin_dir+plugin_prefix+qdb.at(0)+plugin_suffix+">");
                    QMessageBox::critical(NULL,APP_NAME,"Critical Error: database plugin <"+qdb.at(0)+
                                          "> not loaded from path <"+plugin_dir+plugin_prefix+qdb.at(0)+plugin_suffix+">");
                    exit(1);
                }
            }else{
                // и тут файла нет, вот же беда так беда. ругаемси и прощаемся с юзером.
                log.slotPut("core",-1,"Critical Error: database plugin <"+qdb.at(0)+
                            "> not found from path <"+plugin_dir+plugin_prefix+qdb.at(0)+plugin_suffix+">");
                QMessageBox::critical(NULL,APP_NAME,"Critical Error: database plugin <"+qdb.at(0)+
                                      "> not found from path <"+plugin_dir+plugin_prefix+qdb.at(0)+plugin_suffix+">");
                exit(1);
            }
        }
    }

    // если исполнение дошло до этого момента, значит плагин баз данных в памяти.
    // инициализируем плагин баз данных
    // end
    log.slotPut("core",2,"Info: start init database");
    app.connect(PlugDB,SIGNAL(sigPutLog(QString,int,QString)),&log,SLOT(slotPut(QString,int,QString)),Qt::DirectConnection);
    if(!PlugDB->qinit(qdb)){
        // общибко инициализации базы данных. ругаемся благим матом.
        log.slotPut("core",-1,"Critical Error: failure init database plugin <"+qdb.at(0)+">");
        QMessageBox::critical(NULL,APP_NAME,"Critical Error: failure init database plugin <"+qdb.at(0)+">");
        exit(1);
    }
    log.slotPut("core",2,"Info: database ok. search login plugin");

// берем строку инициализации логин плагина игрузим его

    QStringList qlogin; // распарсенные опции подключения базы данных
        if(paramsLogin!=""){
            // в параметрах приложения была указана строка базы данных
            qlogin=paramsLogin.split(",");

        }else{
            // строка указана небыла, пробуем выдернуть с конфига
            // предварительно проверям есть ли конфиг вообще.
            if(next){
                // конфиг то тютю. ругаемся матом.
                log.slotPut("core",1,"Error: read configuration fail");
                QMessageBox::critical(NULL,APP_NAME,"Error: read configuration fail");
                exit(1);
            }else{
                // конфиг есть.
            qlogin=cfg->value("main/login","").toString().split(",");

            }
        }
        // проверяем размер qlogin, если оно не равно хотябы 1 то косякс, ругаемся и выходим.

        if(qlogin.size()==0){
            // тушите свечи сударь.
            log.slotPut("core",1,"Error: login plugin not set");
            QMessageBox::critical(NULL,APP_NAME,"Error: login plugin not set");
            exit(1);
        }

    bool login_plug_enabled=false; // индикатор состояния плагина логина, загружен или нет.
    TsIfaceLoginPlugin * PlugLogin; // указатель на плагин логина
    if(QFile::exists(paramsPlPath+plugin_prefix+qlogin.at(0)+plugin_suffix)){
        // файлег есть, подключаем плагин.
        QPluginLoader ldr;
        ldr.setFileName(paramsPlPath+plugin_prefix+qlogin.at(0)+plugin_suffix);
        if(ldr.load()){
            // плагин загружен, инициализируем.
            login_plug_enabled=true;
            PlugLogin = qobject_cast<TsIfaceLoginPlugin*>(ldr.instance());
            log.slotPut("core",2,"Success: load login plugin <"+qlogin.at(0)+
                        "> from path <"+paramsPlPath+plugin_prefix+qlogin.at(0)+plugin_suffix+">");
        }else{
            // плагин по этому пути не был загружен, ничего страшного, может по след путям загрузится
            log.slotPut("core",2,"Error: login plugin <"+qlogin.at(0)+
                        "> not loaded from path <"+paramsPlPath+plugin_prefix+qlogin.at(0)+plugin_suffix+">");
        }
    }else{
        // файлега нету, ищем дальше
        log.slotPut("core",2,"Information: login plugin <"+qlogin.at(0)+
                    "> not found from path <"+paramsPlPath+plugin_prefix+qlogin.at(0)+plugin_suffix+">");
        // следующий файлег должен лежать по пути из конфига
        // для начала проверяем есть ли конфиг вообще =)
        if(!next){
            log.slotPut("core",2,"Information: config found");
            // конфиг есть, лопатим конфиг и проверяем наличие файлега по этому пути

            if(QFile::exists(cfg->value("main/plugins","").toString()
                +plugin_prefix+qlogin.at(0)+plugin_suffix)){

                // файлен есть, загружаем плугин
                QPluginLoader ldr;
                ldr.setFileName(cfg->value("main/plugins","").toString()
                                +plugin_prefix+qlogin.at(0)+plugin_suffix);
                if(ldr.load()){
                    log.slotPut("core",2,"Success: load login plugin <"+qlogin.at(0)+
                                "> from path <"+cfg->value("main/plugins","").toString()
                                +plugin_prefix+qlogin.at(0)+plugin_suffix+">");
                    // плагин загружен, инициализируем.
                    login_plug_enabled=true;
                    PlugLogin = qobject_cast<TsIfaceLoginPlugin*>(ldr.instance());
                }else{
                    // плагин по этому пути не был загружен, ничего страшного, может по след путям загрузится
                    log.slotPut("core",2,"Error: login plugin <"+qlogin.at(0)+
                                "> not loaded from path <"+cfg->value("main/plugins","").toString()
                                +plugin_prefix+qlogin.at(0)+plugin_suffix+">");
                }
            }else{
                // и тут файлега нету, да и черт с ним.

            }
        }
        //конфига нету, да и черт с ним, идем по пути прописаному статично
        if(!login_plug_enabled){

            // из конфига не поймали, значит ищем по дефолтному пути
            if(QFile::exists(QString(plugin_dir)+QString(plugin_prefix)+qlogin.at(0)+QString(plugin_suffix))){
                // файлен есть, загружаем плугин

                QPluginLoader ldr;
                ldr.setFileName(QString(plugin_dir)+QString(plugin_prefix)+qlogin.at(0)+QString(plugin_suffix));
                if(ldr.load()){
                    // плагин загружен, инициализируем.
                    login_plug_enabled=true;
                    PlugLogin = qobject_cast<TsIfaceLoginPlugin*>(ldr.instance());
                    log.slotPut("core",2,"Success: load login plugin <"+qlogin.at(0)+
                                "> from path <"+QString(plugin_dir)+
                                QString(plugin_prefix)+qlogin.at(0)+QString(plugin_suffix)+">");
                }else{
                    // плагин и по этому пути не был загружен, вот это уже беда, и критическая, ругаемси и тушим свечи.
                    log.slotPut("core",-1,"Critical Error: login plugin <"+qlogin.at(0)+
                                "> not loaded from path <"+plugin_dir+plugin_prefix+qlogin.at(0)+plugin_suffix+">");
                    QMessageBox::critical(NULL,APP_NAME,"Critical Error: login plugin <"+qlogin.at(0)+
                                          "> not loaded from path <"+plugin_dir+plugin_prefix+qlogin.at(0)+plugin_suffix+">");
                    exit(1);
                }
            }else{
                // и тут файла нет, вот же беда так беда. ругаемси и прощаемся с юзером.
                log.slotPut("core",-1,"Critical Error: login plugin <"+qlogin.at(0)+
                            "> not found from path <"+plugin_dir+plugin_prefix+qlogin.at(0)+plugin_suffix+">");
                QMessageBox::critical(NULL,APP_NAME,"Critical Error: login plugin <"+qlogin.at(0)+
                                      "> not found from path <"+plugin_dir+plugin_prefix+qlogin.at(0)+plugin_suffix+">");
                exit(1);
            }
        }
    }

// инициализируем плагин логина
    log.slotPut("core",2,"Info: start init login plugin");
    // асинхронный режим
    app.connect(PlugLogin,SIGNAL(sigQexec(QString,QString,QList<QVariant>)),
                PlugDB,SLOT(slotQexec(QString,QString,QList<QVariant>)));
    app.connect(PlugDB,SIGNAL(sigFinishErr(QString,QString)),PlugLogin,SLOT(slotDbErr(QString,QString)));
    app.connect(PlugDB,SIGNAL(sigFinish(QString,int,QSqlQuery*)),PlugLogin,SLOT(slotDb(QString,int,QSqlQuery*)));
    app.connect(PlugLogin,SIGNAL(sigPutLog(QString,int,QString)),&log,SLOT(slotPut(QString,int,QString)));
    app.connect(PlugLogin,SIGNAL(sigClear(int)),PlugDB,SLOT(slotClear(int)));
    // синхронный режим
    app.connect(PlugLogin,SIGNAL(sigQstartS(QString)),PlugDB,SLOT(slotQstartS(QString)));
    app.connect(PlugLogin,SIGNAL(sigQexecS(QString,QString,QList<QVariant>)),
                PlugDB,SLOT(slotQexecS(QString,QString,QList<QVariant>)));
    app.connect(PlugLogin,SIGNAL(sigQstopS(QString)),PlugDB,SLOT(slotQstopS(QString)));
    app.connect(PlugDB,SIGNAL(sigRstartS(QString)),PlugLogin,SLOT(slotRstartS(QString)));
    app.connect(PlugDB,SIGNAL(sigFinishErrS(QString,QString)),
                PlugLogin,SLOT(slotFinishErrS(QString,QString)));
    app.connect(PlugDB,SIGNAL(sigFinishS(QString,QSqlQuery*)),
                PlugLogin,SLOT(slotFinishS(QString,QSqlQuery*)));

    if(!PlugLogin->qinit(qlogin)){
        // общибко инициализации плагина логина. ругаемся благим матом.
        log.slotPut("core",-1,"Critical Error: failure init login plugin <"+qlogin.at(0)+">");
        QMessageBox::critical(NULL,APP_NAME,"Critical Error: failure init login plugin <"+qlogin.at(0)+">");
        exit(1);
    }

    log.slotPut("core",2,"Info: login plugin ok. start it.");
    if(!PlugLogin->qstart()){
        // юзверь отказался от входа. ну и выходим.
        log.slotPut("core",2,"Info: Login rejected by user. exit.");
        exit(0);
    }
    // ну вот если и до сюда дошли, значит юзер залогинился. уря.
    log.slotPut("core",2,"Info: Success logon user as <"+PlugLogin->getUsername()+">");
    // рисуем сплашскрин. в отладочном режиме автоматически его уберать не будем. в релизе надо бы убрать
    QSplashScreen splash(QPixmap("../share/pixmaps/torisakura_splash_logo.png"));
    splash.show();

    // тут вызывем спец объект, который запрашивает в базе список плагинов для этого юзера, и конфиги для
    // плагинов, тем самым мы можем гибко распределить права в модулях для разных пользователей.
    // без этого объекта было бы слишком геморно работать с бд из этого места. таки дела.
    TsIniter initer(PlugLogin->getUsername());
    initer.connect(&initer,SIGNAL(sigQexec(QString,QString,QList<QVariant>)),
                   PlugDB,SLOT(slotQexec(QString,QString,QList<QVariant>)),Qt::DirectConnection);
    initer.connect(PlugDB,SIGNAL(sigFinishErr(QString,QString)),
                   &initer,SLOT(slotDbErr(QString,QString)),Qt::DirectConnection);
    initer.connect(PlugDB,SIGNAL(sigFinish(QString,int,QSqlQuery*)),
                   &initer,SLOT(slotDb(QString,int,QSqlQuery*)),Qt::DirectConnection);
    initer.connect(&initer,SIGNAL(sigPutLog(QString,int,QString)),
                   &log,SLOT(slotPut(QString,int,QString)),Qt::DirectConnection);
    initer.connect(&initer,SIGNAL(sigClear(int)),PlugDB,SLOT(slotClear(int)));
    splash.showMessage(QString("Loading plugins list ... "), Qt::AlignBottom,Qt::white);
    if(!initer.qstart()){
        // обшибко инициализации. вот беда то.

        log.slotPut("core",-1,"Critical error: failure get list plugins for user. exit");
        QMessageBox::critical(NULL,APP_NAME,"Critical Error: failure get list plugins for user. exit");
        exit(1);
    }
    splash.showMessage(QString("Loading plugins list ...... done."), Qt::AlignBottom,Qt::white);
// а теперь из инитера вынимаем списог. и подключаем плагины с параметрами.
    QList<QStringList> d=initer.getList();
    // список указателей на рабочие плагины
    log.slotPut("core",3,"Debug: start cycle loading wrk plugins");
    QList<TsIfaceWrkPlugin *> wrklist;
    for(int i = 0; i < d.size() ; i++){
        // цикл подключения плагинов из списка. что бы продолжить необходимо 2 плагина
        splash.showMessage(QString("Load plugin ... %1  - %2 of %3").arg(d.at(i).at(0))
                           .arg(QString::number(i+1)).arg(QString::number(d.size())),
                           Qt::AlignBottom,Qt::white);
        log.slotPut("core",2,"Info: start load plugin <"+d.at(i).at(0)+
                    "> with config string <"+d.at(i).at(1)+">");
        // ну понеслась искать этот плугин и включать.

        bool plug_enabled=false; // индикатор состояния плагина
        TsIfaceWrkPlugin * Plug; // указатель на плагин
        if(QFile::exists(paramsPlPath+plugin_prefix+d.at(i).at(0)+plugin_suffix)){
            // файлег есть, подключаем плагин.
            QPluginLoader ldr;
            ldr.setFileName(paramsPlPath+plugin_prefix+d.at(i).at(0)+plugin_suffix);
            if(ldr.load()){
                // плагин загружен, инициализируем.
                plug_enabled=true;
                Plug = qobject_cast<TsIfaceWrkPlugin*>(ldr.instance());
                log.slotPut("core",2,"Success: load plugin <"+d.at(i).at(0)+
                            "> from path <"+paramsPlPath+plugin_prefix+d.at(i).at(0)+plugin_suffix+">");
            }else{
                // плагин по этому пути не был загружен, ничего страшного, может по след путям загрузится
                log.slotPut("core",2,"Error: plugin <"+d.at(i).at(0)+
                            "> not loaded from path <"+paramsPlPath+plugin_prefix+d.at(i).at(0)+plugin_suffix+">");
            }
        }else{
            // файлега нету, ищем дальше
            log.slotPut("core",2,"Information: plugin <"+d.at(i).at(0)+
                        "> not found from path <"+paramsPlPath+plugin_prefix+d.at(i).at(0)+plugin_suffix+">");
            // следующий файлег должен лежать по пути из конфига
            // для начала проверяем есть ли конфиг вообще =)
            if(!next){
                log.slotPut("core",2,"Information: config found");
                // конфиг есть, лопатим конфиг и проверяем наличие файлега по этому пути

                if(QFile::exists(cfg->value("main/plugins","").toString()
                    +plugin_prefix+d.at(i).at(0)+plugin_suffix)){

                    // файлен есть, загружаем плугин
                    QPluginLoader ldr;
                    ldr.setFileName(cfg->value("main/plugins","").toString()
                                    +plugin_prefix+d.at(i).at(0)+plugin_suffix);
                    if(ldr.load()){
                        log.slotPut("core",2,"Success: load plugin <"+d.at(i).at(0)+
                                    "> from path <"+cfg->value("main/plugins","").toString()
                                    +plugin_prefix+d.at(i).at(0)+plugin_suffix+">");
                        // плагин загружен, инициализируем.
                        plug_enabled=true;
                        Plug = qobject_cast<TsIfaceWrkPlugin*>(ldr.instance());
                    }else{
                        // плагин по этому пути не был загружен, ничего страшного, может по след путям загрузится
                        log.slotPut("core",2,"Error: plugin <"+d.at(i).at(0)+
                                    "> not loaded from path <"+cfg->value("main/plugins","").toString()
                                    +plugin_prefix+d.at(i).at(0)+plugin_suffix+">");
                    }
                }else{
                    // и тут файлега нету, да и черт с ним.

                }
            }
            //конфига нету, да и черт с ним, идем по пути прописаному статично
            if(!plug_enabled){

                // из конфига не поймали, значит ищем по дефолтному пути
                if(QFile::exists(QString(plugin_dir)+QString(plugin_prefix)+d.at(i).at(0)+QString(plugin_suffix))){
                    // файлен есть, загружаем плугин

                    QPluginLoader ldr;
                    ldr.setFileName(QString(plugin_dir)+QString(plugin_prefix)+d.at(i).at(0)+QString(plugin_suffix));
                    if(ldr.load()){
                        // плагин загружен, инициализируем.
                        plug_enabled=true;
                        Plug = qobject_cast<TsIfaceWrkPlugin*>(ldr.instance());
                        log.slotPut("core",2,"Success: load plugin <"+d.at(i).at(0)+
                                    "> from path <"+QString(plugin_dir)+
                                    QString(plugin_prefix)+d.at(i).at(0)+QString(plugin_suffix)+">");
                    }else{
                        // плагин и по этому пути не был загружен, вот это уже беда, и критическая, ругаемси и тушим свечи.
                        log.slotPut("core",-1,"Critical Error: plugin <"+d.at(i).at(0)+
                                    "> not loaded from path <"+plugin_dir+plugin_prefix+d.at(i).at(0)+plugin_suffix+">");
                        QMessageBox::critical(NULL,APP_NAME,"Critical Error: plugin <"+d.at(i).at(0)+
                                              "> not loaded from path <"+plugin_dir+plugin_prefix+d.at(i).at(0)+
                                              plugin_suffix+">");
                        exit(1);
                    }
                }else{
                    // и тут файла нет, вот же беда так беда. ругаемси и прощаемся с юзером.
                    log.slotPut("core",-1,"Critical Error: plugin <"+d.at(i).at(0)+
                                "> not found from path <"+plugin_dir+plugin_prefix+d.at(i).at(0)+plugin_suffix+">");
                    QMessageBox::critical(NULL,APP_NAME,"Critical Error: plugin <"+d.at(i).at(0)+
                                          "> not found from path <"+plugin_dir+plugin_prefix+d.at(i).at(0)+plugin_suffix+">");
                    exit(1);
                }
            }
        }
        // инициализируем загруженный плагин
        log.slotPut("core",2,"Info: start init plugin <"+d.at(i).at(0)+">");
        splash.showMessage(QString("Init plugin ... %1  - %2 of %3").arg(d.at(i).at(0))
                           .arg(QString::number(i+1)).arg(QString::number(d.size())),
                           Qt::AlignBottom,Qt::white);
        // соединяем плагины с базой
        app.connect(Plug,SIGNAL(sigPutLog(QString,int,QString)),&log,SLOT(slotPut(QString,int,QString)));
        app.connect(Plug,SIGNAL(sigQexec(QString,QString,QList<QVariant>)),
                    PlugDB,SLOT(slotQexec(QString,QString,QList<QVariant>)));
        app.connect(PlugDB,SIGNAL(sigFinishErr(QString,QString)),Plug,SLOT(slotDbErr(QString,QString)));
        app.connect(PlugDB,SIGNAL(sigFinish(QString,int,QSqlQuery*)),Plug,SLOT(slotDb(QString,int,QSqlQuery*)));
        app.connect(Plug,SIGNAL(sigClear(int)),PlugDB,SLOT(slotClear(int)));
        // синхронный режим
        app.connect(Plug,SIGNAL(sigQstartS(QString)),PlugDB,SLOT(slotQstartS(QString)));
        app.connect(Plug,SIGNAL(sigQexecS(QString,QString,QList<QVariant>)),
                    PlugDB,SLOT(slotQexecS(QString,QString,QList<QVariant>)));
        app.connect(Plug,SIGNAL(sigQstopS(QString)),PlugDB,SLOT(slotQstopS(QString)));
        app.connect(PlugDB,SIGNAL(sigRstartS(QString)),Plug,SLOT(slotRstartS(QString)));
        app.connect(PlugDB,SIGNAL(sigFinishErrS(QString,QString)),
                    Plug,SLOT(slotFinishErrS(QString,QString)));
        app.connect(PlugDB,SIGNAL(sigFinishS(QString,QSqlQuery*)),
                    Plug,SLOT(slotFinishS(QString,QSqlQuery*)));

        if(!Plug->qinit(d.at(i).at(1),PlugLogin->getUsername(),paramsFb,&wrklist)){
            // общибко инициализации плагина логина. ругаемся благим матом.
            log.slotPut("core",-1,"Critical Error: failure init plugin <"+d.at(i).at(0)+">");
            QMessageBox::critical(NULL,APP_NAME,"Critical Error: failure init plugin <"+d.at(i).at(0)+">");
            exit(1);
        }

        // все гуд, добавляем его в список загруженных и инициализированных.
        splash.showMessage(QString("Load plugin ... %1 ... done - %2 of %3").arg(d.at(i).at(0))
                           .arg(QString::number(i+1)).arg(QString::number(d.size())),
                           Qt::AlignBottom,Qt::white);
        wrklist.append(Plug);
    }

    log.slotPut("core",3,"Debug: stop cycle loading wrk plugins");
    // отрисовываем главный диалог
    MainWin mw(&wrklist);
    splash.finish(&mw);
    if(mw.exec()){
        exit(0);
    }else{
        exit(0);
    }

// инициализируем плагины пользователя, передаем им режимы их работы.

// отображаем главное окно. ждем событий.

    return app.exec();
}
